package com.lu.spzx.log.aspect;

import com.lu.spzx.log.annotation.Log;
import com.lu.spzx.log.service.AsyncOperLogService;
import com.lu.spzx.log.utils.LogUtil;
import com.lu.spzx.model.entity.system.SysOperLog;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

// 环绕通知切面类定义
@Aspect
@Component
@Slf4j
public class LogAspect {

    @Autowired
    private AsyncOperLogService asyncOperLogService;


    /**
     * 切入点表达式
     * 方式一: 可以通过直接配置全路径的方式
     *
     * @Around("@annotation(com.lu.spzx.log.annotation.Log)") 方式二: 可以通过在参数列表中声明注解类型,表达式中配置指定注解类型的变量
     * @Around("@annotation(sysLog)") 本质上没有区别, 只是形式上不同, 推荐使用方式二, 第二种方式在操作过程中更加方便, 可以直接获取被增强方法的独有数据
     */
    @Around("@annotation(sysLog)")
//    @Around("@annotation(sysLog)")
    public Object doAroundAdvice(ProceedingJoinPoint joinPoint, Log sysLog) {
        // 构建前置参数
        SysOperLog sysOperLog = new SysOperLog();
        LogUtil.beforeHandleLog(sysLog, joinPoint, sysOperLog);

        Object proceed = null;
        try {
            // 执行业务方法
            proceed = joinPoint.proceed();

            // 构建响应结果参数
            LogUtil.afterHandleLog(sysLog, proceed, sysOperLog, 0, null);
        } catch (Throwable e) {
            // 业务方法执行产生异常
            e.printStackTrace();
            // 打印异常信息
            LogUtil.afterHandleLog(sysLog, proceed, sysOperLog, 1, e.getMessage());
        }

        // 保存日志数据
        this.asyncOperLogService.saveSysOperLog(sysOperLog);
        return proceed;
    }
}